package com.hibase.core.web.aspect;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson.JSON;
import com.hibase.common.entity.ValidationResult;
import com.hibase.common.exception.HibaseException;
import com.hibase.common.util.UserContext;
import com.hibase.common.util.ValidationUtil;
import com.hibase.core.web.annotation.HibaseValid;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * 类备注：
 *
 * @author hufeng
 * @version 1.0
 * @date 2019-03-27 21:39
 * @desc
 * @since 1.8
 */
@Component
@Aspect
@Slf4j
public class GlobalRequestAspect {

    @Value("${hibase.performance.bad.value:3000}")
    private int performanceBadValue;

    @Pointcut("@annotation(com.hibase.core.web.annotation.HibasePostRequestMapping) || " +
            "@annotation(com.hibase.core.web.annotation.HibaseGetRequestMapping) || " +
            "@annotation(com.hibase.core.web.annotation.HibasePatchRequestMapping) || " +
            "@annotation(com.hibase.core.web.annotation.HibaseDeleteRequestMapping) || " +
            "@annotation(com.hibase.core.web.annotation.HibasePutRequestMapping) || " +
            "@annotation(com.hibase.core.web.annotation.HibaseRequestMapping)")
    public void pointCut() {
    }

    @Around("pointCut()")
    public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable {
        TimeInterval timer = DateUtil.timer();
        Object response;
        if(log.isDebugEnabled()){
            log.debug("执行Controller开始: " + pjp.getSignature() + " 参数：" + CollUtil.newArrayList(pjp.getArgs()).toString());
        }
        // 校验参数是否合法
        this.checkParam(pjp);
        // 执行业务操作
        response = pjp.proceed(pjp.getArgs());
        try {
            if(log.isDebugEnabled()){
                log.debug("执行Controller结束: " + pjp.getSignature() + "， 返回值：" + JSON.toJSONString(response));
            }

        } catch (Exception ex) {
            if(log.isDebugEnabled()){
                log.debug(pjp.getSignature() + " 接口记录返回结果失败！，原因为：{}", ex.getMessage());
            }
        }
        Long consumeTime = timer.interval();
        if(log.isDebugEnabled()){
            log.debug("耗时：" + consumeTime + "(毫秒).");
        }
        //当接口请求时间大于3秒时，标记为异常调用时间，并记录入库
        if (consumeTime > performanceBadValue) {
//                DcPerformanceEntity dcPerformanceEntity = new DcPerformanceEntity();
//                dcPerformanceEntity.setInterfaceName(pjp.getSignature().toString());
//                dcPerformanceEntity.setRequestParam(Lists.newArrayList(pjp.getArgs()).toString());
//                dcPerformanceEntity.setConsumeTime(consumeTime + "毫秒");
//                RabbitMQMessageTarget mqTarget = RabbitMQMessageTarget.createFanoutTarget(ProjectConstants.DC_KEY_EXCHANGE_PERFORMANCE, new String[]{ProjectConstants.DC_KEY_QUEUE_PERFORMANCE});
//                rabbitMQService.send(mqTarget, JSON.toJSONString(dcPerformanceEntity));
            // 暂时只打日志，不做记录
            log.warn(pjp.getSignature().toString() + "请求超出指定时间");
        }
        UserContext.clear();
        return response;
    }

    private void checkParam(ProceedingJoinPoint pjp) {
        if (pjp != null) {
            Object[] objects = pjp.getArgs();
            if (ArrayUtil.isNotEmpty(objects)) {
                for (Object object : objects) {
                    if (object != null && object.getClass() != null) {
                        HibaseValid hibaseValid = object.getClass().getAnnotation(HibaseValid.class);
                        if (hibaseValid != null) {
                            ValidationResult result = ValidationUtil.validateEntity(object);
                            if (result.hasErrors()) {
                                throw new HibaseException(result.getDefaultMessage());
                            }
                        }
                    }
                }
            }
        }
    }

}
